/*******************************************************************************
 * Copyright (c) 2011 Erik Byström.
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/
package se.slackers.automatunes.algorithm;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import se.slackers.automatunes.audio.Note;
import se.slackers.automatunes.audio.Playable;
import se.slackers.automatunes.ui.IntParameter;
import se.slackers.automatunes.ui.ParameterSet;
import se.slackers.automatunes.util.Pair;

/**
 * @author Erik Byström
 * 
 */
public class SumAudioRule extends BaseAudioRule {
	private static final String CHANNEL = "Midi Channel";
	private static final String MAX_NOTES = "Max notes";

	private final ParameterSet parameters = new ParameterSet();
	private final Scale scale = new BluesScale();

	public SumAudioRule() {
		parameters.add(new IntParameter(CHANNEL, 1, 0, 127).tooltip("MIDI Channel to play on"));
		parameters.add(new IntParameter(MAX_NOTES, 3, 1, 10).tooltip("Maximum notes per step"));
	}

	@Override
	public int channel() {
		return parameters.getInt(CHANNEL);
	}

	@Override
	public ParameterSet parameters() {
		return parameters;
	}

	@Override
	public void process(final Playable playable, final Field field) {
		final float columnMax = field.height();
		final int max = parameters.getInt(MAX_NOTES);

		final List<Pair<Float, Integer>> columns = new ArrayList<Pair<Float, Integer>>(field.width());
		for (int x = 0; x < field.width(); x++) {
			final float sum = sumColumn(field, x);
			if (sum > 0) {
				columns.add(Pair.create(sum, x));
			}
		}
		Collections.sort(columns);

		final Iterator<Pair<Float, Integer>> iterator = columns.iterator();
		for (int i = 0; i < max && iterator.hasNext(); i++) {
			final Pair<Float, Integer> pair = iterator.next();
			final int note = scale.translate(pair.second());
			final int velocity = (int) (128 + 128 * columnMax / pair.first());
			playable.noteOn(new Note(note, velocity));
		}

		turnOffOtherNotes(playable);
	}

	private float sumColumn(final Field field, final int x) {
		float sum = 0;
		for (int y = 0; y < field.height(); y++) {
			sum += field.get(x, y);
		}
		return sum;
	}
}
